/*
 * Aritmetico.h
 *
 *  Created on: 03/06/2010
 *      Author: sebastian
 */

#ifndef ARITMETICO_H_
#define ARITMETICO_H_
#define FIN_DE_ARCHIVO 256

#include "Contexto.h"

#define TAM_BUFFER 512/4

class Aritmetico{

private:

	unsigned underflow;

	unsigned rangoInferior;

	unsigned rangoSuperior;

	FILE* archivoComprimido;

	unsigned* buffer;

	int indiceBuffer;

	unsigned actual;

	int indiceActual;

	//arma el intervalo segun las probabilidades de los caracteres
	void armarIntervalo(Contexto* contexto, TIntervalo &intervalo);

	//arma un intervalo ficticio para el contexto ficticio menos 1
	void armarIntervaloMenosUno(TLetraExt letra, TIntervalo&intervalo);

	//verifica y resuelve overflow en piso y techo
	unsigned verificarOverflow();

	//verifica y resuelve underflow en piso y techo
	unsigned verificarUnderflow();

	//busca el caracter pedido en el intervalo
	TIntervalo::iterator* buscarCaracter(TLetraExt letra, TIntervalo& intervalo);

	//calcula el nuevo techo con el shift y rellenando con 1's
	void calcularNuevoTechoOverflow(unsigned total);

	//calcula el nuevo techo con el shift y rellenando con 0's
	void calcularNuevoPisoOverflow(unsigned total);

	//calcula el nuevo techo con el shift y rellenando con 1's
	void calcularNuevoTechoUnderflow(unsigned total);

	//calcula el nuevo techo con el shift y rellenando con 0's
	void calcularNuevoPisoUnderflow(unsigned total);

	//agrega un nuevo bit
	void agregarBit(unsigned bit);

	//agrega un nuevo byte al buffer
	void agregarByte();

	//escribe el buffer al archivo de salida
	void escribirArchivo();

	//lee del archivo al buffer
	void leerArchivo();

	//ultima emision
	void emitirPiso();

	//busca el caracter correspondiente al numero emitido
	TIntervalo::iterator* buscarNumero(TIntervalo& intervalo);

	//emite un overflow de total bits (comprimiendo)
	void emitirOverflow(unsigned total);

	//resuelve un underflow de total bits (comprimiendo)
	void manejarUnderflow(unsigned total);

	//resuelve un underflow de total bits (descomprimiendo)
	void resolverUnderflow(unsigned total);

	//resuelve un overflow de total bits (descomprimiendo)
	void resolverOverflow(unsigned total);

	//descarta un bit de la ventana y lo reemplaza por el siguiente del archivo
	void descartarBit();

	//busca el caracter por su offset en un invervalo ficticio
	TLetraExt* buscarIntervaloMenosUno();

	//corro la ventana de inspeccion total posiciones a partir de la segunda
	void descartarUnderflow(unsigned total);

public:

	Aritmetico();

	~Aritmetico();

	//asigna un archivo destino
	void asignarArchivo(FILE* archivoDestino);

	// unsigned = NULL => ESC
	// codigo ASCII: 0 a 255 - EOF: 256
	//contexto = NULL => CTX-(-1)
	void comprimir(Contexto* contexto, TLetraExt* letra);

	// unsigned = NULL => ESC
	// codigo ASCII: 0 a 255 - EOF: 256
	//contexto = NULL => CTX-(-1)
	TLetraExt* descomprimir(Contexto* contexto);

	//lee del archivo comprimido el primer numero para trabajar
	void inicializarNumero();

};

#endif /* ARITMETICO_H_ */
